Podsumowanie analizy

W ramach niniejszego zadania pracowano na danych pochodzących z trzech elektrowni słonecznych we Włoszech. Celem pracy była próba przewidzenia energii wytwarzanej przez panele fotowoltaiczne w oparciu o historyczne dane. W pierwszym kroku przeanalizowano posiadany zbiór danych pod kątem występowania tzw. missing values. Problemem okazało się rozróżnianie wartości prawidłowych od wartości brakujących, ponieważ te drugie reprezentowane były przez wartość zero, która w innym przypadku była wartością prawidłową. Na podstawie ilości wytworzonej energii wyodrębniono przypadki brakującej wartości promieniowania słonecznego irradiamento, a następnie oszacowano dla nich możliwą wartość w oparciu o pomiary innych czujników wykonane o tej samej godzinie, tego samego dnia. Następnie sprawdzono korelacje występujące między poszczególnymi zmiennymi analizowanego zbioru danych. Zgodnie z przypuszczeniami, okazało się, że największy wpływ na ilość wytwarzanej energii ma między innymi ilość promieniowania słonecznego oraz wilgotność powietrza. Atrybuty te wykorzystano do stworzenia modelu regresji, wykorzystując metodę lm czyli regresję liniową.

Przygotowanie środowiska

Przed przystąpieniem do analizy posiadanych danych, przygotowano środowisko niezbędne do pracy. Przygotowanie to polegało między innymi na załadowaniu niezbędnych bibliotek oraz zapewnieniu powtarzalności wyników.

Wykorzystane biblioteki

Podczas realizacji zadania wykorzystano następujące biblioteki:

library(dplyr)
library(knitr)
library(caret)
library(plotly)
library(ggplot2)
library(reshape2)

Zapewnienie powtarzalności wyników

Powtarzalność wyników zapewniono ustawiając stałe ziarno:

set.seed(3)

Wstępne przetworzenie danych

Po wczytaniu danych poddano je wstępnej obróbce. Zajęto się analizą a następnie obróbką brakujących danych.

Wczytanie danych

Dane wczytano do zmiennej raw_df wykorzystując funkcję read.csv():

raw_df <- read.csv("elektrownie.csv")

Przetworzenie brakujących danych

W związku z tym, że przetwarzane dane pochodzą z czujników, które mogły ulegać awarii, bądź były wyłączone przez pewien czas, w danych tych możliwe jest występowanie wartości pustych, nieokreślonych czy zerowych. Z tego powodu, w miejscu tym dokonano przeglądu analizowanych danych i poddano je obróbce. Ponieważ w posiadanym zbiorze, wartości brakujące reprezentowane są przez wartość 0, ciężko jest ocenić, które z wystąpnień tej wartości są wartościami prawidłowymi, a które brakującymi. Udało się to dla atrybutu irradiamento. Jeśli wytworzono energię, tzn. kwh > 0 a wartość irradiamento jest równa 0, oznacza to, że jest to wartość brakująca, ponieważ w przeciwnym razie panel nie wytworzyłby energii. Znalezione w ten sposób wartości puste zastąpiono średnią wartością promieniowania o danej godzinie w danym dniu.

# skopiowanie danych
my_df <- raw_df

# wyodrebnienie danych zawierajacych brakujace wartosci promieniowania
missing_irradiamento <- my_df %>% filter(irradiamento == 0, kwh > 0)

# wyznaczenie pozostalej czesci zbioru danych
occurring_irradiamento <- setdiff(my_df, missing_irradiamento)

# zamiana wartosci brakujacych na oszacowana wartosc sredniej
missing_irradiamento$irradiamento <- apply(missing_irradiamento, 1, function (row) {
    similar_data <- my_df %>%
        filter(
            data == row[["data"]]
        )
    
    row[["irradiamento"]] <- mean(similar_data[["irradiamento"]])
})

# sklejenie fragmentow zbioru z powrotem w jeden
my_df <- rbind(occurring_irradiamento, missing_irradiamento)

Analiza posiadanych danych

Po wstępnym przygotowaniu danych przystąpiono do ich analizy. Przebadano między innymi wartości przyjmowane przez poszczególne atrybuty jak również korelację między poszczególnymi zmiennymi. Przygotowano również wykresy zmiany wytwarzanej energii w czasie i przestrzeni.

Podsumowanie zbioru danych

Analizowany zbiór danych zawiera informacje na temat energii, wytwarzanej przez panele fotowoltaiczne. Dane te pochodzą z trzech elektrowni słonecznych we Włoszech. Zbiór danych składa się z 235790 wierszy. Każdy z nich zawiera średnie wartości pomiarów wyznaczane co godzinę dla pojedynczego czujnika. Poza wartościami wytwarzanej energii i znacznikami czasowymi, dla każdego z czujników przechowywane są dane geograficzne i pogodowe. W sumie każdy z wierszy opisany jest przez 51 atrybutów. Są to:

##  [1] "id"                   "idsito"               "idmodel"             
##  [4] "idbrand"              "lat"                  "lon"                 
##  [7] "ageinmonths"          "anno"                 "day"                 
## [10] "ora"                  "data"                 "temperatura_ambiente"
## [13] "irradiamento"         "pressure"             "windspeed"           
## [16] "humidity"             "icon"                 "dewpoint"            
## [19] "windbearing"          "cloudcover"           "tempi"               
## [22] "irri"                 "pressurei"            "windspeedi"          
## [25] "humidityi"            "dewpointi"            "windbearingi"        
## [28] "cloudcoveri"          "dist"                 "altitude"            
## [31] "azimuth"              "altitudei"            "azimuthi"            
## [34] "pcnm1"                "pcnm2"                "pcnm3"               
## [37] "pcnm4"                "pcnm5"                "pcnm6"               
## [40] "pcnm7"                "pcnm8"                "pcnm9"               
## [43] "pcnm10"               "pcnm11"               "pcnm12"              
## [46] "pcnm13"               "pcnm14"               "pcnm15"              
## [49] "irr_pvgis_mod"        "irri_pvgis_mod"       "kwh"

Analiza wartości atrybutów

Wszystkie dane znajdujące się w analizowanym zbiorze, za wyjątkiem identyfikatora pomiaru (id), roku (anno) oraz pełnej daty (data), są znormalizowane. Z tego powodu ich analiza jest utrudniona. W tabeli poniżej przedstawiono wartości podstawowych statystyk dla wybranych atrybutów omawianego zbioru. Statystyki te to: wartość minimalna, wartość maksymalna, średnia arytmetyczna, mediana, pierwszy i trzeci kwartyl, a także liczba unikalnych wartości.

Wartość najmniejsza Pierwszy kwartyl Mediana Średnia arytmetyczna Trzeci kwartyl Wartość największa Liczba unikalnych wartości
temperatura_ambiente 0.045 0.212 0.348 0.3734429 0.530 0.818 52
irradiamento 0.000 0.000 0.041 0.1116034 0.209 0.710 3198
pressure 0.000 0.748 0.753 0.6504251 0.755 0.769 41
windspeed 0.000 0.042 0.066 0.0762241 0.102 0.696 367
humidity 0.160 0.540 0.700 0.6843925 0.840 1.000 85
dewpoint 0.139 0.535 0.619 0.6055304 0.683 0.865 634
windbearing 0.000 0.300 0.478 0.4512351 0.660 0.769 360
cloudcover 0.000 0.230 0.310 0.3590429 0.510 1.000 101
altitude 0.111 0.419 0.564 0.5463627 0.681 0.884 773
azimuth 0.128 0.295 0.425 0.4545834 0.635 0.818 689
kwh 0.000 0.000 0.049 0.1687714 0.332 1.000 864

Korelacja między zmiennymi

Podczas wyznaczania macierzy korelacji pominięto atrybut data, ponieważ jest on typu Factor, natomiast funkcja cor() wymaga danych numerycznych.

# wyznaczenie macierzy korelacji (pominiecie atrybutu 11 - data)
cor_matrix <- cor(my_df[, -11])

# przeksztalcenie macierzy korelacji
cor_df <- melt(cor_matrix)

Jak widać na poniższym wykresie, ilość wytworzonej energii kwh jest znacząco skorelowana między innymi z promieniowaniem irradiamento (pozytywnie) oraz z wilgotnością powietrza humidity (negatywnie). Współczynniki tych korelacji wynoszą odpowiednio: 0.8757128 i -0.5319679. Oczywistym jest fakt, że nie wszystkie znalezione zależności mają odzwierciedlenie w rzeczywistości, np. wartość idsito (identyfikator czujnika) nie zależy od szerokości geograficznej lat czy ciśnienia atmosferycznego pressure jak mogłyby wskazywać współczynniki korelacji między tymi zmiennymi. Podobnie nie należy szukać zależności między szerokością geograficzną lat a długością geograficzną lon. Warto zwrócić jednak uwagę np. na korelację pomiędzy godziną (ora) a azymutem (azimuth), który określa położenie Słońca na niebie (kierunek geograficzny wyrażony w mierze kątowej). W godzinach porannych Słońce znajduje się po wschodniej stronie nieba, natomiast wieczorem po stronie zachodniej.

Zmiana wytwarzanej energii w czasie i przestrzeni

Poniższy wykres przedstawia zmianę wytwarzanej energii w czasie i przestrzeni. Aby pokazać/ukryć serie danych należy kliknąć na żądanej pozycji legendy (każda seria danych to dane z jednego czujnika). Korzystając z suwaka na dole możliwa jest zmiana zakresu czasu.

Przewidywanie przyszłej produkcji energii

Posiadając historyczne dane dotyczące wytwarzanej energii, można pokusić się o estymację dalszej produkcji, w oparciu o te dane. Jedną z metod jest stworzenie regresora.

Próba stworzenia regresora przewidującego wytwarzaną energię przez każdy panel w ujęciu godzinowym

W pierwszym kroku, przed stworzeniem regresora, sprawdzono, od których zmiennych najbardziej zależy ilość wytwarzanej energii. W tym celu wykorzystano sporządzoną wcześniej macierz korelacji:

# stworzenie prostego data frame'u zawierajacego nazwe atrybutu i wartosc jego korelacji z atrybutem kwh
cor_with_kwh <- data.frame(names(my_df[, -11]), unname(cor_matrix["kwh",]))
names(cor_with_kwh) <- c("arg", "value")

# posortowanie wynikow i wybranie 10 najbardziej skorelowanych zmiennych z kwh
cor_with_kwh %>%
    arrange(desc(abs(value))) %>% # abs - niewazne czy korelacja pozytywna czy negatywna
    head(11) # 11. jest korelacja kwh z kwh
##                     arg      value
## 1                   kwh  1.0000000
## 2          irradiamento  0.8757128
## 3         irr_pvgis_mod  0.8423077
## 4              humidity -0.5319679
## 5              azimuthi -0.4887478
## 6                  irri  0.4023656
## 7              altitude  0.4000177
## 8                 tempi  0.2463286
## 9                  dist -0.2275743
## 10       irri_pvgis_mod  0.2270132
## 11 temperatura_ambiente  0.2054987

Najlepsze wyniki otrzymano dla pięciu najbardziej skorelowanych zmiennych. Trafność regresji oszacowano na podstawie miary RMSE (Root-Mean-Square Error).

# podzial zbioru na uczacy i testowy
inTraining <- createDataPartition(
    y = my_df$idsito,
    p = 0.75,
    list = FALSE
)

trainingSet <- my_df[inTraining,]
testingSet <- my_df[-inTraining,]

# podzial zbioru uczacego na uczacy i walidacyjny
trainCtrl <- trainControl(
    method = "repeatedcv",
    number = 2,
    repeats = 5
)

# szukanie modelu
model <- train(
    kwh ~ idsito + irradiamento + irr_pvgis_mod + humidity + azimuthi + irri,
    data = trainingSet,
    method = "lm",
    metric = "RMSE",
    trControl = trainCtrl
)

# zastosowanie modelu do zbioru testowego
prediction <- predict(model, newdata = testingSet)

# wyswietlenie wynikow
results <- data.frame(obs =  testingSet$kwh, pred = prediction)
defaultSummary(results)
##       RMSE   Rsquared        MAE 
## 0.09628357 0.79162571 0.05823460

Analiza ważności atrybutów najlepszego znalezionego modelu regresji

Nie ulega wątpliwości fakt, że ilość wytwarzanej przez elektrownie słoneczne energii w największym stopniu zależy od wartości promieniowania. Jego brak jest jednoznaczny z brakiem energii produkowanej przez panele fotowoltaiczne. Innym parametrem pogodowym, który ma istotny wpływ na ilość wytwarzanej energii jest wilgotność powietrza. Im więcej pary wodnej znajduje się w powietrzu, tym więcej promieniowania słonecznego jest przez nią absorbowane i rozpraszane, a co za tym idzie w mniejszym stopniu promieniowanie to dociera do panelu fotowoltaicznego. Ilość wytwarzanej energii zależy także od azymutu Słońca, czyli od jego położenia.